#include "Car.h"
#include "CustomModel.h"

Car::Car(void):
PhysicObject(b2_dynamicBody, 100, 150, "car1_50"),
hP(25), accelerating(0), stearing(0), trackCovered(0), laps(0), realoading(0), mineReloading(1)
{
	b2PolygonShape shape;
	shape.SetAsBox(1, 2);
	width = 2 * Config::PHYSIC_SCALE;
	height = 4 * Config::PHYSIC_SCALE;

	b2FixtureDef fix;
	fix.density = 1;
	fix.friction = 0.5;
	fix.restitution = 0.5;
	fix.shape = &shape;

	addFixture(&fix);

	body->SetLinearDamping(2);
	body->SetAngularDamping(13);


	speedVector.SetZero();
	applyPoint = body->GetLocalCenter();
	force = 1;

	reloadPointer = new FatPointer <Car, void>(this, METHOD(void, Car, reload)); 
	reloadTimer.addEventListaner(GTimer::TIMER_EVENT, reloadPointer);
	reloadTimer.setTimer(1000, 0);
	reloadTimer.start();

	minePointer = new FatPointer <Car, void>(this, METHOD(void, Car, reloadMine)); 
	mineTimer.addEventListaner(GTimer::TIMER_EVENT, minePointer);
	mineTimer.setTimer(1000, 0);
	mineTimer.start();

	trackTestPointer = new FatPointer<Car, void>(this, METHOD(void, Car, testTrackCovered));

	this->viewMode = "TRANSPARENT";

	engineSound.loadWave("data/car_idle.wav");
	engineSound.setVolume(100);
	engineSound.play(1);
}

Car::~Car(void)
{
}

void Car::stearLeft()
{
	if(!stearing)
	{
		stearing = true;
		applyPoint.Set(1, 0);
		applyPoint = body->GetWorldPoint(applyPoint);
		if(!accelerating && (force > 1))
		{
			speedVector.Set(0, -1 * force);
			speedVector = body->GetWorldVector(speedVector);
			force -= .2;
		}
	}
}

void Car::stearRight()
{
	if(!stearing)
	{
		stearing = true;
		applyPoint.Set(-1, 0);
		applyPoint = body->GetWorldPoint(applyPoint);
		if(!accelerating && (force > 1))
		{
			speedVector.Set(0, -1 * force);
			speedVector = body->GetWorldVector(speedVector);
			force -= .2;
		}
	}
}

void Car::accelerate()
{
	accelerating = true;
	if(force < hP)
		force += 0.5;
	speedVector.Set(0, -1 * force);
	speedVector = body->GetWorldVector(speedVector);
	applyPoint = body->GetWorldCenter();
}

void Car::slowDown()
{
	force -= 0.3;
	if(body->GetLinearVelocity().Length() < 3 && body->GetAngularVelocity() < 1 || force < -1)
	{
		if(force < -1)
		{
			force = -10;
			speedVector.Set(0, -1 * force);
			speedVector = body->GetWorldVector(speedVector);
		}
	}
}

void Car::fireCannon()
{
	if(!realoading)
	{
	b2Vec2 barrel(0, -2.2);//2.1
	b2Vec2 fireVel(0, -800);
	b2Vec2 blowBack(0, 400);
	barrel = body->GetWorldPoint(barrel);
	fireVel = body->GetWorldVector(fireVel);
	blowBack = body->GetWorldVector(blowBack);

	CannonBall *ball = new CannonBall( barrel.x * Config::PHYSIC_SCALE, barrel.y * Config::PHYSIC_SCALE);
	Model::getModel()->addPassiveObject(ball);
	ball->body->ApplyLinearImpulse(fireVel, barrel);
	body->ApplyLinearImpulse(blowBack, barrel);
	/*fireVel.Set(0, -50);
	fireVel = body->GetWorldVector(fireVel);
	body->ApplyLinearImpulse(fireVel, barrel);*/
	realoading = true;
	reloadTimer.start();
	}
}

void Car::placeMine()
{
	if(!mineReloading)
	{
		b2Vec2 placePoint(0, 2.8);
		placePoint = body->GetWorldPoint(placePoint);

		Bomb *mine = new Bomb(placePoint.x * Config::PHYSIC_SCALE, placePoint.y * Config::PHYSIC_SCALE);
		mine->myself = &Model::getModel()->addActiveObject(mine);
		mineReloading = true;
		mineTimer.start();
		static_cast<CustomModel *>(Model::getModel())->dManager.addBomb(mine);
	}
}

void Car::update()
{
	//static_cast<CustomModel *>(CustomModel::getModel())->engineSound.play(1);
	engineSound.setPitch( 600 *(1 + speedVector.Length()/20) );

	body->ApplyLinearImpulse(speedVector, applyPoint);

	speedVector.SetZero();
	if(force > 1)
		force -= 0.1;
	if(force < -1)
		force += 0.1;
	accelerating = false;
	stearing = false;

}

void Car::reload(Event *e)
{
	realoading = false;
	reloadTimer.stop();
}

void Car::reloadMine(Event *e)
{
	mineReloading = false;
	mineTimer.stop();
}

void Car::testTrackCovered(GameObject **a, GameObject **b)
{
	if(!trackCovered && static_cast<TrackCoverTester*>(*b)->id == 1)
		return;

	trackCovered |= static_cast<TrackCoverTester*>(*b)->id;
	if(trackCovered == 3)
	{
		trackCovered = 0;
		laps++;
	}
}
